AZSocketIOを使ってiOSアプリからnode.js+Socket.IOと双方向通信する
前回iOSアプリからnode.js+Socket.IOと双方向通信する | Developers.IOではsocket.IO-objcを紹介しました。このライブラリは非常に優秀なのですが、接続に失敗した場合に別のトランスポートへの再接続処理を自動でやってくれませんでした(知ってたら教えてください!)。
で、今回紹介するAZSocketIOはその再接続処理も行ってくれるなんとも便利なライブラリです。AZSocketIOは使い方も非常に簡単です。というわけで早速使ってみませう。
サーバ側の実装
さて、サーバ側は前回に引き続き弊社うえじゅん氏が公開しているNode + Socket.IO で簡単なチャットアプリの作成 | Developers.IOで作ったチャットアプリを使用しますので、先にチャットアプリを作っちゃっちゃってください。
プロジェクトの準備
チャットアプリの準備が終わったら、早速iOSアプリ側の準備をしましょう。ここからは以下の環境を前提に説明します。
- OS X 10.9
- Xcode 5.0.2
- iOS SDK 7.0
さて、テキトーにプロジェクトを作りましょう。ここではSingle View ApplicationでAZSocketIOという名前でプロジェクトを作成しました。
AZSocketIOをCocoaPodsでインストール
プロジェクトディレクトリ配下にPodfileを作成して、以下のように記述してください。
pod 'AZSocketIO'
pod installを実行すると、勝手にSocketRocketとAFNetworkingがインストールされます。ちょっと残念なのが、AFNetworking 2.xには対応していないため、1.3.xがインストールされてしまいます。。。
これで、インストール完了です。
早速つないでみる
ViewController.mを開き、以下のように記述してみましょう。
#import "ViewController.h" #import <AZSocketIO/AZSocketIO.h> @interface ViewController () // Socket.IOクライアント @property (nonatomic, strong) AZSocketIO *socketIO; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // ホストとポート番号を指定してAZSocketIOインスタンス生成 self.socketIO = [[AZSocketIO alloc] initWithHost:@"localhost" andPort:@"3000" secure:NO]; // メッセージを受信した時に実行されるBlocks [self.socketIO setMessageRecievedBlock:^(id data) { NSLog(@"data: %@", data); }]; // イベントを受信したときに実行されるBlocks [self.socketIO setEventRecievedBlock:^(NSString *eventName, id data) { NSLog(@"eventName: %@, data: %@", eventName, data); }]; // エラーを受信したときに実行されるBlocks [self.socketIO setErrorBlock:^(NSError *error) { NSLog(@"error: %@", error); }]; // 切断されたときに実行されるBlocks [self.socketIO setDisconnectedBlock:^{ NSLog(@"Disconnected!"); }]; // 接続開始 [self.socketIO connectWithSuccess:^{ NSLog(@"Success connecting!"); } andFailure:^(NSError *error) { NSLog(@"Failure connecting. error: %@", error); }]; } @end
たったこれだけです!簡単ですね。すごーく大まかな流れは、
- AZSocketIOインスタンスの作成してプロパティに保持(メソッド抜けたらなくなっちゃうのでw)
- 処理したいコールバックに処理を書く
- 接続開始!
と非常にシンプルですね。
サーバを起動しておきつつデバッグ実行したらブラウザからメッセージを送信してみましょう。すると、以下のようにXcodeのコンソールにログが出力されます。
AZSocketIOインスタンスの作成
さて、AZSocketIOインスタンスの作成には、以下のメソッドが用意されています。
- (id)initWithHost:(NSString *)host andPort:(NSString *)port secure:(BOOL)secureConnections
- (id)initWithHost:(NSString *)host andPort:(NSString *)port secure:(BOOL)secureConnections withNamespace:(NSString *)endpoint
説明は不要ですねw
hostにはホスト名(http://とかは無し)、portは文字列で指定するってことぐらいでしょうか?基本的にこのインスタンスを使ってサーバとのやりとりを行うようになります。なので、生成したインスタンスはどっかで保持しておきましょう。
もろもろのタイミングで呼ばれるBlocksたち
接続を開始してからは以下の4つのBlocksが適宜呼ばれます。
- messageRecievedBlock
- メッセージを受信した時に実行されるBlocks
- eventRecievedBlock
- イベントを受信したときに実行されるBlocks
- disconnectedBlock
- エ切断されたときに実行されるBlocks
- errorBlock
- エラーを受信したときに実行されるBlocks
これらのBlocksを設定するには、それぞれ以下のメソッドを使用します。
- (void)setMessageRecievedBlock:(void (^)(id data))messageRecievedBlock
- (void)setEventRecievedBlock:(void (^)(NSString *eventName, id data))eventRecievedBlock
- (void)setDisconnectedBlock:(void (^)())disconnectedBlock
- (void)setErrorBlock:(void (^)(NSError *error))errorBlock
イベント受信時の処理に関してはイベント毎にコールバック用のBlocksを設定できます。その場合は- (void)addCallbackForEventName:(NSString *)name callback:(void (^)(NSString *eventName, id data))block
メソッドを使用します。
// message:receiveイベント受信時の処理 [self.socketIO addCallbackForEventName:@"message:receive" callback:^(NSString *eventName, id data) { NSLog(@"eventName: %@, data: %@", eventName, data); }];
尚、- (void)addCallbackForEventName:(NSString *)name callback:(void (^)(NSString *eventName, id data))block
メソッドで追加されたイベントはmessageRecievedBlockでは処理されないようになります。
ここで登録したコールバック用のBlocksは、- (BOOL)removeCallbackForEvent:(NSString *)name callback:(void (^)(NSString *eventName, id data))block
メソッドや- (NSInteger)removeCallbacksForEvent:(NSString *)name
メソッドで削除できます。
接続と切断
準備ができたら接続を開始します。
接続の開始と切断は非常に簡単です。開始するときは- (void)connectWithSuccess:(void (^)())success andFailure:(void (^)(NSError *error))failure
メソッドを、切断するときは- (void)disconnect
メソッドを実行するだけです。
// 接続開始 [self.socketIO connectWithSuccess:^{ NSLog(@"Success connecting!"); } andFailure:^(NSError *error) { NSLog(@"Failure connecting. error: %@", error); }]; // 切断 [self.socketIO disconnect];
接続完了時は成功・失敗のときにそれぞれ設定したBlocksが実行され、切断した場合はdisconnectedBlockが実行されます。
データの送信
データの送信の話に入る前に、StoryboardからViewControllerにテキストフィールドと送信ボタンを配置してそれぞれアウトレットとアクションを定義しておきましょう。
データを送信するためには、以下のように記述します。
- (IBAction)sendEventButtonTapped:(id)sender { NSString *message = self.textField.text; // テキストフィールドが入力されていたら、その内容をmessage:sendイベントで送信する if (message && message.length > 0) { [self.socketIO emit:@"message:send" args:@{@"message" : message} error:NULL]; } }
AZSocketIOでは送信系のメソッドとして以下のメソッドが用意されています。
- send系
- (BOOL)send:(id)data error:(NSError * __autoreleasing *)error
- (BOOL)send:(id)data error:(NSError *__autoreleasing *)error ackWithArgs:(void (^)(NSArray *data))callback
- (BOOL)send:(id)data error:(NSError *__autoreleasing *)error ack:(void (^)())callback
- emit系
- (BOOL)emit:(NSString *)name args:(id)args error:(NSError * __autoreleasing *)error
- (BOOL)emit:(NSString *)name args:(id)args error:(NSError *__autoreleasing *)error ackWithArgs:(void (^)(NSArray *data))callback
- (BOOL)emit:(NSString *)name args:(id)args error:(NSError *__autoreleasing *)error ack:(void (^)())callback
これまた簡単!
設定できる値
プロパティ | 型 | 説明 |
---|---|---|
reconnect | BOOL | 再接続処理を実行するか。デフォルトはYES。 |
reconnectionDelay | NSTimeInterval | 初回の再接続処理を何秒後に実行するか設定できる。デフォルトは0.5。 |
reconnectionLimit | NSTimeInterval | 再接続処理の遅延秒数の上限を指定できる。デフォルトはMAX_FLOAT。 |
maxReconnectionAttempts | NSUInteger | 再接続処理の最大試行回数。デフォルトは10。 |
これらの設定値は以下のように指定します。
// ホストとポート番号を指定してAZSocketIOインスタンス生成 self.socketIO = [[AZSocketIO alloc] initWithHost:@"localhost" andPort:@"3000" secure:NO]; self.socketIO.reconnect = YES; self.socketIO.reconnectionDelay = 1.0; self.socketIO.reconnectionLimit = 2048.0; self.socketIO.maxReconnectionAttempts = 5;
AZSocketIOでは、接続に失敗した場合、reconnectがYESであれば再接続を試みます。再接続処理に失敗すると、以降はreconnectionDelayを2倍に設定しなおして再接続処理を行います。なので、デフォルトだとreconnectionDelayは0.5、1.0、2.0、4.0、8.0、・・・と増えていきます。
まとめ
ご覧の通り、使い方は非常に簡単ですね!ネックなのは、前述した通りAFNetworking2.xに対応していない点ですね。。。まぁこの点を加味しても非常に有用なライブラリだと思いますので、是非使ってみてください!